home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / pctim12.zip / GCCINT8.C < prev    next >
Text File  |  1995-01-29  |  6KB  |  223 lines

  1. #include <dos.h>
  2. #include <dpmi.h>
  3. #include <pc.h>
  4. #include "gccint8.h"
  5.  
  6. #define IRQ0 0x8
  7. #define PIT0 0x40
  8. #define PIT1 0x41
  9. #define PIT2 0x42
  10. #define PITMODE 0x43
  11. #define PITCONST 1193180L
  12. #define PIT0DEF 18.2067597
  13. #define KBCTRL 0x61
  14. #define NEW8H 1
  15.  
  16. static float    tick_per_ms = 0.0182068;
  17. static float    ms_per_tick = 54.9246551;
  18. static float    freq8h = 18.2067597;
  19. static unsigned char flag8h = 0;
  20. static _go32_dpmi_seginfo rm_old_handler,
  21.                 rm_new_handler,
  22.                 pm_old_handler,
  23.                 pm_new_handler;
  24. static _go32_dpmi_registers r,
  25.                 r1;
  26.  
  27. volatile int    counter_8h;
  28. volatile int    counter_reset;
  29. volatile unsigned long int ticks_8h;
  30.  
  31. void            init8h(unsigned int Hz)
  32. {
  33.     unsigned int    pit0_set,
  34.                     pit0_value;
  35.  
  36.     if (flag8h != NEW8H) {
  37.         disable();
  38.  
  39.         _go32_dpmi_get_protected_mode_interrupt_vector(8, &pm_old_handler);
  40.         pm_new_handler.pm_offset = (int) pm_new8h;
  41.         pm_new_handler.pm_selector = _go32_my_cs();
  42.         _go32_dpmi_chain_protected_mode_interrupt_vector(8, &pm_new_handler);
  43.  
  44.         _go32_dpmi_get_real_mode_interrupt_vector(8, &rm_old_handler);
  45.         rm_new_handler.pm_offset = (int) rm_new8h;
  46.         _go32_dpmi_allocate_real_mode_callback_iret(&rm_new_handler, &r1);
  47.         _go32_dpmi_set_real_mode_interrupt_vector(8, &rm_new_handler);
  48.  
  49.         outportb(PITMODE, 0x36);
  50.         pit0_value = PITCONST / Hz;
  51.         pit0_set = (pit0_value & 0x00ff);
  52.         outportb(PIT0, pit0_set);
  53.         pit0_set = (pit0_value >> 8);
  54.         outportb(PIT0, pit0_set);
  55.  
  56.         enable();
  57.  
  58.         flag8h = NEW8H;
  59.         freq8h = Hz;
  60.         counter_8h = 0;
  61.         counter_reset = freq8h / PIT0DEF;
  62.         tick_per_ms = freq8h / 1000;
  63.         ms_per_tick = 1000 / freq8h;
  64.     }
  65. }
  66.  
  67. void            quit8h(void)
  68. {
  69.     unsigned int    pit0_set,
  70.                     pit0_value;
  71.     unsigned long   tick;
  72.     char           *cmostime;
  73.  
  74.     if (flag8h == NEW8H) {
  75.  
  76.         disable();
  77.  
  78.         outportb(PITMODE, 0x36);
  79.         outportb(PIT0, 0x00);
  80.         outportb(PIT0, 0x00);
  81.  
  82.         _go32_dpmi_set_real_mode_interrupt_vector(8, &rm_old_handler);
  83.         _go32_dpmi_set_protected_mode_interrupt_vector(8, &pm_old_handler);
  84.         _go32_dpmi_free_real_mode_callback(&rm_new_handler);
  85.  
  86.         enable();
  87.  
  88.         cmostime = get_cmostime();
  89.         tick = PIT0DEF *
  90.             (
  91.              (((float) *cmostime) * 3600) +
  92.              (((float) *(cmostime + 1)) * 60) +
  93.              (((float) *(cmostime + 2)))
  94.             );
  95.         biostime(1, tick);
  96.  
  97.         flag8h = 0;
  98.         freq8h = PIT0DEF;
  99.         counter_reset = freq8h / PIT0DEF;
  100.         tick_per_ms = freq8h / 1000;
  101.         ms_per_tick = 1000 / freq8h;
  102.     }
  103. }
  104.  
  105. void            rm_new8h(void)
  106. {
  107.     ticks_8h++;
  108.     counter_8h++;
  109.  
  110.     if (counter_8h == counter_reset) {
  111.         counter_8h = 0;
  112.         memset(&r, 0, sizeof(r));
  113.         r.x.cs = rm_old_handler.rm_segment;
  114.         r.x.ip = rm_old_handler.rm_offset;
  115.         r.x.ss = r.x.sp = 0;
  116.         _go32_dpmi_simulate_fcall_iret(&r);
  117.         /* Note. You should use "r.x.cs = 0xf000; r.x.ip = 0xfea5;" instead
  118.          * of "r.x.cs = rm_old_handler.rm_segment; r.x.ip =
  119.          * rm_old_handler.rm_offset;" if your gcc version is older than
  120.          * 2.6.3. This is because of a bug in gcc 2.6.0. PCTIMER for gcc was
  121.          * first developed under gcc 2.6.0, and it was found that the
  122.          * following instructions: "r.x.cs = rm_old_handler.rm_segment;
  123.          * r.x.ip = rm_old_handler.rm_offset; r.x.ss = r.x.sp = 0;
  124.          * _go32_dpmi_simulate_fcall_iret(&r);" could not call
  125.          * rm_old_handler.rm_segment:rm_old_handler.rm_offset correctly.
  126.          * Therefore, my solution in PCTIMER 1.1 was to call f000:fea5, which
  127.          * is the default handler of int 8h in IBM PC and fully compatible
  128.          * BIOSes. Since the bug has been fixed in gcc 2.6.3, the
  129.          * "rm_new8h" handler should also be revised. */
  130.     } else {
  131.         outportb(0x20, 0x20);
  132.     }
  133. }
  134.  
  135. void            pm_new8h(void)
  136. {
  137.     ticks_8h++;
  138.     counter_8h++;
  139.  
  140.     if (counter_8h == counter_reset) {
  141.         counter_8h = 0;
  142.     } else {
  143.         outportb(0x20, 0x20);
  144.     }
  145. }
  146.  
  147. unsigned long   time8h(unsigned long start, unsigned long stop)
  148. {
  149.     unsigned long   duration,
  150.                     millisec;
  151.  
  152.     if (stop < start)
  153.         return 0;
  154.     else {
  155.         duration = stop - start;
  156.         millisec = duration * ms_per_tick;
  157.         return millisec;
  158.     }
  159. }
  160.  
  161. void            delay8h(unsigned int delayms)
  162. {
  163.     unsigned long int delaybegin = 0;
  164.     unsigned long int delayend = 0;
  165.     unsigned int    delaytick;
  166.  
  167.     delaytick = delayms * tick_per_ms;
  168.  
  169.     if (flag8h == NEW8H)
  170.         delaybegin = ticks_8h;
  171.     else
  172.         delaybegin = biostime(0, 0);
  173.  
  174.     do {
  175.         if (flag8h == NEW8H)
  176.             delayend = ticks_8h;
  177.         else
  178.             delayend = biostime(0, 0);
  179.     } while ((delayend - delaybegin) < delaytick);
  180. }
  181.  
  182. void            sound8h(int freq, int duration)
  183. {
  184.     int             byte;
  185.     unsigned int    freq1;
  186.  
  187.     freq1 = PITCONST / freq;
  188.     outportb(PITMODE, 0xb6);
  189.     byte = (freq1 & 0xff);
  190.     outportb(PIT2, byte);
  191.     byte = (freq1 >> 8);
  192.     outportb(PIT2, byte);
  193.     byte = inportb(KBCTRL);
  194.     outportb(KBCTRL, (byte | 3));
  195.  
  196.     delay8h(duration);
  197.     outportb(KBCTRL, (byte & 0xfc));
  198. }
  199.  
  200. char           *get_cmostime(void)
  201. {
  202.     char           *buff;
  203.     static char     buffer[6];
  204.     char            ch;
  205.  
  206.     buff = buffer;
  207.     memset(&r, 0, sizeof(r));
  208.     r.h.ah = 0x02;
  209.     _go32_dpmi_simulate_int(0x1a, &r);
  210.  
  211.     ch = r.h.ch;
  212.     buffer[0] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
  213.     ch = r.h.cl;
  214.     buffer[1] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
  215.     ch = r.h.dh;
  216.     buffer[2] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
  217.     buffer[3] = r.h.dl;
  218.     buffer[4] = (char) (r.x.flags & 0x0001);
  219.     buffer[5] = 0x00;
  220.  
  221.     return (buff);
  222. }
  223.